;; -------- dashboard --------
(use-package dashboard
  :ensure t
  :config
  (dashboard-setup-startup-hook)
  (setq dashboard-banner-logo-title "Hello 元辰")
  ;; (setq dashboard-startup-banner nil)
  (setq dashboard-items '((recents  . 20)
                          ;; (bookmarks . 5)
                          ;; (projects . 5)
                          ;; (agenda . 5)
                          ;; (registers . 5)
                          ))
  (when (display-graphic-p)
    (setq dashboard-set-heading-icons t)
    (setq dashboard-set-file-icons t))
  (setq dashboard-set-init-info t)
  ;; (setq dashboard-init-info "Enjoy counting the parentheses!")
  ;; (setq dashboard-set-footer nil)
  (setq dashboard-footer-messages '("Enjoy counting the parentheses!")))

;; -------- set frame size --------
(defun p1uxtar-Win-frame-size ()
  "Frame size for Win."
  (interactive)
  (cond
   ((string= p1frame "max")
    (p1uxtar-medium-frame-size))
   ((string= p1frame "med")
    (p1uxtar-max-frame-size-Win))))
(defun p1uxtar-max-frame-size-Win ()
  "Frame size be maximum (for Win)."
  (interactive)
  (set-frame-position (selected-frame) 0 1)
  (set-frame-size (selected-frame)
                  (- (x-display-pixel-width) 18)
                  (- (x-display-pixel-height) 40) t)
  (setq p1frame "max"))
(defun p1uxtar-medium-frame-size ()
  "Frame size not be maximum."
  (interactive)
  (set-frame-position (selected-frame)
                      (round (* (x-display-pixel-width) 0.4))
                      (round (* (x-display-pixel-height) 0.3)))
  (set-frame-size (selected-frame)
                  (round (* (x-display-pixel-width) 0.5))
                  (round (* (x-display-pixel-height) 0.6)) t)
  (setq p1frame "med"))
(cond
 ((eq system-type 'gnu/linux)
  (toggle-frame-maximized))
 ((eq system-type 'windows-nt)
  (setq p1frame "med")
  (p1uxtar-Win-frame-size)))

;; -------- ace-window --------
(use-package ace-window
  :preface
  (defun toggle-window-split ()
    (interactive)
    (if (= (count-windows) 2)
        (let* ((this-win-buffer (window-buffer))
               (next-win-buffer (window-buffer (next-window)))
               (this-win-edges (window-edges (selected-window)))
               (next-win-edges (window-edges (next-window)))
               (this-win-2nd (not (and (<= (car this-win-edges)
                                           (car next-win-edges))
                                       (<= (cadr this-win-edges)
                                           (cadr next-win-edges)))))
               (splitter
                (if (= (car this-win-edges)
                       (car (window-edges (next-window))))
                    'split-window-horizontally
                  'split-window-vertically)))
          (delete-other-windows)
          (let ((first-win (selected-window)))
            (funcall splitter)
            (if this-win-2nd (other-window 1))
            (set-window-buffer (selected-window) this-win-buffer)
            (set-window-buffer (next-window) next-win-buffer)
            (select-window first-win)
            (if this-win-2nd (other-window 1))))))
  :bind
  (("C-o" . 'ace-window))
  ;; :custom-face
  ;; (aw-leading-char-face ((t (:inherit font-lock-keyword-face :bold t :height 3.0))))
  ;; (aw-mode-line-face ((t (:inherit mode-line-emphasis :bold t))))
  :config
  ;; (setq aw-ignore-current t)
  ;; (custom-set-variables
  ;;  '(aw-keys (quote (97 115 100 102 103 104 106 107 108))))
  (defhydra hydra-horizontal-windows (global-map "<f10>" :hint nil)
    ("[" shrink-window-horizontally)
    ("]" enlarge-window-horizontally)
    ("{" shrink-window)
    ("}" enlarge-window)
    ("+" balance-windows)
    ("-" split-window-vertically)
    ("/" split-window-horizontally)
    ("," previous-buffer)
    ("." next-buffer)
    ("<f10>" p1uxtar-Win-frame-size :exit t)
    ("r" toggle-window-split)
    ("s" ace-swap-window :exit t)
    ("o" other-window)
    ("d" ace-delete-window)
    ("D" kill-buffer-and-window)
    ("q" nil))

  (which-key-add-key-based-replacements
    "<f10> [" "shrink"
    "<f10> ]" "enlarge"
    "<f10> +" "balance")
  )

;; ;; -------- all-the-icons --------
(use-package all-the-icons
  :if window-system
  :config
  (declare-function memoize 'memoize)
  (declare-function memoize-restore 'memoize)
  (defun all-the-icons-reset ()
    "Reset (unmemoize/memoize) the icons."
    (interactive)
    (ignore-errors
      (dolist (f '(all-the-icons-icon-for-file
                   all-the-icons-icon-for-mode
                   all-the-icons-icon-for-url
                   all-the-icons-icon-family-for-file
                   all-the-icons-icon-family-for-mode
                   all-the-icons-icon-family))
        (memoize-restore f)
        (memoize f)))
    (message "Reset all-the-icons"))
  (add-to-list 'all-the-icons-icon-alist
               '("^Rakefile$" all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.go$" all-the-icons-fileicon "go" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\go.mod$" all-the-icons-fileicon "go" :face all-the-icons-dblue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\go.sum$" all-the-icons-fileicon "go" :face all-the-icons-dpurple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(go-mode all-the-icons-fileicon "go" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(xwidget-webkit-mode all-the-icons-faicon "chrome" :v-adjust -0.1 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(bongo-playlist-mode all-the-icons-material "playlist_play" :height 1.2 :v-adjust -0.2 :face 'all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(bongo-library-mode all-the-icons-material "library_music" :height 1.1 :v-adjust -0.2 :face 'all-the-icons-dgreen))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-group-mode all-the-icons-fileicon "gnu" :face 'all-the-icons-silver))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-summary-mode all-the-icons-octicon "inbox" :height 1.0 :v-adjust 0.0 :face 'all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gnus-article-mode all-the-icons-octicon "mail" :height 1.1 :v-adjust 0.0 :face 'all-the-icons-lblue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(message-mode all-the-icons-octicon "mail" :height 1.1 :v-adjust 0.0 :face 'all-the-icons-lblue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(diff-mode all-the-icons-octicon "git-compare" :v-adjust 0.0 :face all-the-icons-lred))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(flycheck-error-list-mode all-the-icons-octicon "checklist" :height 1.1 :v-adjust 0.0 :face all-the-icons-lred))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.rss$" all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(elfeed-search-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(elfeed-show-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-mode all-the-icons-faicon "rss-square" :v-adjust -0.1 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-list-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(newsticker-treeview-item-mode all-the-icons-octicon "rss" :height 1.1 :v-adjust 0.0 :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.[bB][iI][nN]$" all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.c?make$" all-the-icons-fileicon "gnu" :face all-the-icons-dorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.conf$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.toml$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(conf-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(conf-space-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(forge-topic-mode all-the-icons-alltheicon "git" :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.xpm$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-dgreen))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(help-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1 :face all-the-icons-purple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(helpful-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1 :face all-the-icons-purple))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(Info-mode all-the-icons-faicon "info-circle" :height 1.1 :v-adjust -0.1))
  (add-to-list 'all-the-icons-icon-alist
               '("NEWS$" all-the-icons-faicon "newspaper-o" :height 0.9 :v-adjust -0.2))
  (add-to-list 'all-the-icons-icon-alist
               '("Cask\\'" all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(cask-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-blue))
  (add-to-list 'all-the-icons-icon-alist
               '(".*\\.ipynb\\'" all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebooklist-mode all-the-icons-faicon "book" :face all-the-icons-lorange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebook-mode all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-orange))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(ein:notebook-multilang-mode all-the-icons-fileicon "jupyter" :height 1.2 :face all-the-icons-dorange))
  (add-to-list 'all-the-icons-icon-alist
               '("\\.epub\\'" all-the-icons-faicon "book" :height 1.0 :v-adjust -0.1 :face all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(nov-mode all-the-icons-faicon "book" :height 1.0 :v-adjust -0.1 :face all-the-icons-green))
  (add-to-list 'all-the-icons-mode-icon-alist
               '(gfm-mode all-the-icons-octicon "markdown" :face all-the-icons-lblue)))

;; -------- centaur-tabs --------
(use-package centaur-tabs
  :ensure t
  :config
  (setq centaur-tabs-style "bar"
        centaur-tabs-set-icons t
        centaur-tabs-gray-out-icons 'buffer
        centaur-tabs-set-bar 'under
        x-underline-at-descent-line t
        centaur-tabs-set-close-button nil)
  (centaur-tabs-mode)
  (defun centaur-tabs-buffer-groups ()
    "`centaur-tabs-buffer-groups' control buffers' group rules.
 Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'.
 All buffer name start with * will group to \"Emacs\".
 Other buffer group by `centaur-tabs-get-group-name' with project name."
    (list
     (cond
	  ;; ((not (eq (file-remote-p (buffer-file-name)) nil))
	  ;; "Remote")
	  ((or (string-equal "*" (substring (buffer-name) 0 1))
	       (memq major-mode '(magit-process-mode
				              magit-status-mode
				              magit-diff-mode
				              magit-log-mode
				              magit-file-mode
				              magit-blob-mode
				              magit-blame-mode
				              )))
	   "Emacs")
	  ((derived-mode-p 'prog-mode)
	   "Editing")
	  ((derived-mode-p 'dired-mode)
	   "Dired")
	  ((memq major-mode '(helpful-mode
			              help-mode))
	   "Help")
	  ((memq major-mode '(org-mode
			              org-agenda-clockreport-mode
			              org-src-mode
			              org-agenda-mode
			              org-beamer-mode
			              org-indent-mode
			              org-bullets-mode
			              org-cdlatex-mode
			              org-agenda-log-mode
			              diary-mode))
	   "OrgMode")
	  (t
	   (centaur-tabs-get-group-name (current-buffer))))))
  (defun centaur-tabs-hide-tab (x)
    "Do no to show buffer X in tabs."
    (let ((name (format "%s" x)))
      (or
       ;; Current window is not dedicated window.
       (window-dedicated-p (selected-window))
       ;; Buffer name not match below blacklist.
       (string-prefix-p "*epc" name)
       (string-prefix-p "*helm" name)
       (string-prefix-p "*Helm" name)
       (string-prefix-p "*Compile-Log*" name)
       (string-prefix-p "*lsp" name)
       (string-prefix-p "*company" name)
       (string-prefix-p "*flycheck" name)
       (string-prefix-p "*Flycheck" name)
       (string-prefix-p "*tramp" name)
       (string-prefix-p " *Mini" name)
       (string-prefix-p "*help" name)
       (string-prefix-p "*straight" name)
       (string-prefix-p " *temp" name)
       (string-prefix-p "*Help" name)
       (string-prefix-p "*mybuf" name)
       ;; (string-prefix-p "*autoconnect-NOX " name)
       ;; (string-prefix-p "*NOX " name)
       (string-prefix-p "*One-Key" name)
       ;; Is not magit buffer.
       (and (string-prefix-p "magit" name)
	        (not (file-name-extension name)))
       ))))

;; -------- mode-line --------

;; Not display minor-mode
;; uncomment when using CLI or custom mode-line
(diminish 'abbrev-mode)
(diminish 'auto-revert-mode)
(add-hook 'emacs-startup-hook
          (lambda ()
            (diminish 'eldoc-mode)
            (diminish 'page-break-lines-mode)))

;; -------- vanilla --------
;; via: xuchengpeng etc
(defvar ml-selected-window nil)
(defun ml-record-selected-window ()
  (setq ml-selected-window (selected-window)))
(defun ml-update-all ()
  (force-mode-line-update t))
(add-hook 'post-command-hook 'ml-record-selected-window)
(add-hook 'buffer-list-update-hook 'ml-update-all)
(defun dotemacs-mode-line-fill (face reserve)
  "Return empty space using FACE and leaving RESERVE space on the right."
  (unless reserve
    (setq reserve 20))
  (when (and (display-graphic-p) (eq 'right (get-scroll-bar-mode)))
    (setq reserve (- reserve 3)))
  (propertize " "
              'display `((space :align-to
                                (- (+ right right-fringe right-margin) ,reserve)))
              'face face))
(defun dotemacs-buffer-encoding-abbrev ()
  "The line ending convention used in the buffer."
  (let ((buf-coding (format "%s" buffer-file-coding-system)))
    (if (string-match "\\(dos\\|gb2312\\|gbk\\|gb18030\\|unix\\|utf-8\\|mac\\)" buf-coding)
        (capitalize (match-string 1 buf-coding))
      buf-coding)))
(setq-default mode-line-format
	          (list
	           mode-line-front-space
	           '(:eval
		         (if (eq ml-selected-window (selected-window))
		             '(:eval (propertize "😄" ;; "☻"
					                     'face 'font-lock-type-face))
		           '(:eval (propertize "🙂" ;; "☺"
				                       'face 'font-lock-keyword-face))))
	           " [" ;; insert vs overwrite mode, input-method in a tooltip
	           '(:eval (propertize (if overwrite-mode "Ovr" "Ins")
				                   'face 'font-lock-keyword-face
				                   'help-echo (concat "Buffer is in "
						                              (if overwrite-mode
							                              "overwrite"
							                            "insert") " mode")))
	           ;; was this buffer modified since the last save?
	           '(:eval (when (buffer-modified-p)
			             (concat "," (propertize "Mod"
						                         'face 'font-lock-warning-face
						                         'help-echo "Buffer has been modified"))))
	           ;; is this buffer read-only?
	           '(:eval (when buffer-read-only
			             (concat "," (propertize "RO"
						                         'face 'font-lock-type-face
						                         'help-echo "Buffer is read-only"))))
	           "] "
	           (propertize "%e" 'face 'font-lock-string-face)
	           ;; mode-line-mule-info
	           ;; mode-line-client
	           ;; mode-line-modified
	           ;; mode-line-remote
	           ;; mode-line-frame-identification
	           ;; mode-line-buffer-identification
	           '(:eval (propertize "%b" 'face 'font-lock-function-name-face
				                   'help-echo (buffer-file-name)))
               '(:eval
                 (when (not (string-match "\*" (buffer-name)))
                   (let* ((crtdirl (split-string (file-name-directory (expand-file-name (buffer-file-name))) "/")))
                     (when (> (length crtdirl) 2)
                       (let* ((rootname (car crtdirl))
                              (snddir (nth 1 crtdirl))
                              (projname (nth 2 crtdirl)))
                         (when (string= (concat rootname "/" snddir)
                                        "d:/project")
                           (propertize (concat " @ " projname)
                                       'face 'font-lock-keyword-face)))))))
	           " ["
	           (propertize "%l" 'face 'font-lock-type-face)
	           ", "
	           (propertize "%c" 'face 'font-lock-type-face)
	           "] ("
	           (propertize "%p" 'face 'font-lock-constant-face)
	           " / "
	           (propertize "%I" 'face 'font-lock-constant-face)
	           ") "
	           '(:eval (dotemacs-buffer-encoding-abbrev)) ;; %z
	           " "
	           mode-line-modes
	           ;; '(:eval (rime-lighter))
	           '(:eval `(vc-mode vc-mode))
	           " "
	           ;; (dotemacs-mode-line-fill 'mode-line 35)
	           ;; mode-line-position
	           '(:eval mode-line-misc-info)
	           mode-line-end-spaces
	           ))

;; -------- line number --------
(eval-after-load 'linum
  '(progn
     (defface linum-leading-zero
       `((t :inherit 'linum
            :foreground ,(face-attribute 'linum :background nil t)))
       "Face for displaying leading zeroes for line numbers in display margin."
       :group 'linum)
     (defun linum-format-func (line)
       (let ((w (length
                 (number-to-string (count-lines (point-min) (point-max))))))
         (concat
          (propertize (make-string (- w (length (number-to-string line))) ?0)
                      'face 'linum-leading-zero)
          (propertize (number-to-string line) 'face 'linum)
          ;; (propertize " ")
          )))
     (setq linum-format 'linum-format-func)))

;; -------- eldoc for eglot --------
(use-package eldoc-box
  :if window-system
  :diminish (eldoc-mode eldoc-box-hover-at-point-mode)
  :hook
  ((eglot--managed-mode . eldoc-box-hover-at-point-mode)
   (eldoc-mode . eldoc-box-hover-at-point-mode)))

;; -------- rainbow-mode for colorizing strings --------
(use-package rainbow-mode
  :defer t
  :diminish rainbow-mode
  :hook
  ((emacs-lisp-mode web-mode css-mode ess-r-mode) . rainbow-mode))

(provide 'UI)
